package vip.liux.front.application.serviceimpl.chat;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import vip.liux.core.exception.BusinessException;
import vip.liux.front.application.service.chat.IConversationAppService;
import vip.liux.front.application.service.chat.IRealTimeChatMessageSender;
import vip.liux.front.application.service.chat.dtos.conversations.ChatConversationDto;
import vip.liux.front.application.service.chat.dtos.conversations.GetConversationInput;
import vip.liux.front.application.service.chat.dtos.conversations.MarkConversationAsReadInput;
import vip.liux.front.application.service.chat.dtos.messages.ChatMessageDto;
import vip.liux.front.application.service.chat.dtos.messages.ChatMessagedDto;
import vip.liux.front.application.service.chat.dtos.messages.SendMessageInput;
import vip.liux.front.application.service.chat.dtos.users.ChatTargetUserInfo;
import vip.liux.front.domain.enums.ChatMessageSide;
import vip.liux.front.domain.models.chat.*;

import java.time.Instant;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static vip.liux.front.domain.models.chat.MessagingManager.Volo_Abp_Chat_010002;
import static vip.liux.front.domain.models.chat.MessagingManager.Volo_Abp_Chat_010003;

@Service
public class ConversationAppService implements IConversationAppService {
    private final MessagingManager messagingManager;
    private final IChatUserLookupService chatUserLookupService;
    private final IChatConversationRepository conversationRepository;
    private final IRealTimeChatMessageSender realTimeChatMessageSender;

    public ConversationAppService(
            MessagingManager messagingManager,
            IChatUserLookupService chatUserLookupService,
            IChatConversationRepository conversationRepository,
            IRealTimeChatMessageSender realTimeChatMessageSender
    ) {
        this.messagingManager = messagingManager;
        this.chatUserLookupService = chatUserLookupService;
        this.conversationRepository = conversationRepository;
        this.realTimeChatMessageSender = realTimeChatMessageSender;
    }

    /**
     * 发生消息给用户.
     *
     * @param input 输入参数
     */
    @Override
    @Transactional
    public void sendMessage(SendMessageInput input, Long userId) {
        // 获取目标用户
        ChatUser targetUser = chatUserLookupService.findUserById(input.targetUserId());

        if (targetUser == null) {
            throw new BusinessException(Volo_Abp_Chat_010002);
        }

        // 获取发送者用户
        ChatUser senderUser = chatUserLookupService.findUserById(userId);

        // 创建消息
        messagingManager.createNewMessage(userId, targetUser.getId(), input.message());

        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                // 发送实时消息
                realTimeChatMessageSender.sendChatMessage(targetUser.getId(), new ChatMessagedDto(
                        senderUser.getId(),
                        senderUser.getUsername(),
                        senderUser.getName(),
                        senderUser.getSurname(),
                        input.message()
                ));
            }
        });
    }

    /**
     * 获取会话.
     *
     * @param input 输入参数
     * @return 会话
     */
    @Override
    public ChatConversationDto getConversation(GetConversationInput input, Long userId) {
        // 获取目标用户
        ChatUser targetUser = chatUserLookupService.findUserById(input.getTargetUserId());

        if (targetUser == null) {
            throw new BusinessException(Volo_Abp_Chat_010003);
        }

        // 组装会话数据
        ChatConversationDto chatConversation = new ChatConversationDto(
                new ArrayList<>(),
                new ChatTargetUserInfo(
                        targetUser.getId(),
                        targetUser.getUsername(),
                        targetUser.getName(),
                        targetUser.getSurname()
                )
        );

        // 读取并获取消息
        List<MessageWithDetails> messages = messagingManager
                .readMessages(userId, targetUser.getId(), (input.getPage() - 1) * input.getMaxResultCount(), input.getMaxResultCount());

        // 添加会话消息数据
        chatConversation.messages().addAll(
                messages.stream().map(x ->
                        new ChatMessageDto(
                                x.message().getText(),
                                x.message().getCreationTime().toInstant(ZoneOffset.UTC),
                                x.message().isAllRead(),
                                Optional.ofNullable(x.message().getReadTime()).orElse(Instant.MAX),
                                ChatMessageSide.values()[x.userMessage().getSide()]
                        )
                ).toList());

        return chatConversation;
    }

    /**
     * 标记会话为已读.
     *
     * @param input 输入参数
     */
    @Override
    public void markConversationAsReadAsync(MarkConversationAsReadInput input, Long userId) {

        // 获取会话
        ConversationPair conversationPair = conversationRepository.findPair(userId, input.targetUserId());

        if (conversationPair.senderConversation().getLastMessageSide() == ChatMessageSide.Receiver.ordinal()) {
            conversationPair.senderConversation().resetUnreadMessageCount();
            conversationRepository.save(conversationPair.senderConversation());
        }
    }
}
